﻿//+-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//Description:  ResourceExtensionRequirementsViewModel
//Author: Aravind Ramarathinam (aravr@microsoft.com)
//
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using VmroleAuthor.Commands;
using VmroleAuthor.Models;

namespace VmroleAuthor.ViewModels
{

    public class ResourceExtensionRequirementsViewModel : TreeViewItemViewModel, IDataErrorInfo, IDataWarningInfo, IProduceValidationResults, IContainOsVhdTags
    {
        private readonly VmRoleResourceExtensionViewModel vmRoleResourceExtensionViewModel;
        private readonly ObservableCollection<OsVhdTagViewModel> osvhdrequirements;
        

        private string newTagToBeAdded;

        private static class PropertyNames
        {
            public const string ResourceRequirementsSummary = "ResourceRequirementsSummary";
            public const string NewTagToBeAdded = "NewTagToBeAdded";
            public const string OSVirtualHardDiskRequirements = "OSVirtualHardDiskRequirements";           
        }

        public ResourceExtensionRequirementsViewModel(
            VmRoleResourceExtensionViewModel resourceExtensionViewModel)
            : base(resourceExtensionViewModel, true)
        {
            this.vmRoleResourceExtensionViewModel = resourceExtensionViewModel;
            if (this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements == null)
            {
                this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements = new ResourceRequirements();
            }
            this.osvhdrequirements = new ObservableCollection<OsVhdTagViewModel>();
            if (this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements == null)
            {
                this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements = new List<string>();
            }
            foreach (var tag in this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements)
            {
                this.osvhdrequirements.Add(new OsVhdTagViewModel(tag, this));
            }

            this.AvailableTags = new List<string>();
            this.AvailableTags.AddRange(RecommendedTags.GeneralTags);
            this.AvailableTags.AddRange(RecommendedTags.MajorVersionTags);
            this.AvailableTags.AddRange(RecommendedTags.ArchitectureTags);
            this.AvailableTags.AddRange(RecommendedTags.ReleaseRelatedTags);
            this.AvailableTags.AddRange(RecommendedTags.ReleaseModifierTags);
            this.AvailableTags.AddRange(RecommendedTags.SQLServerTags);
            this.AvailableTags.AddRange(RecommendedTags.PrerequistiesTags);

            this.AddOsVhdTagCommand = new RelayCommand(
                param => this.AddTag((string)param),
                param => this.CanAddTag((string)param));

            this.ValidationResults = new ObservableCollection<CloudServiceModelValidationResult>();
        }


        public string ResourceRequirementsSummary
        {
            get
            {
                int count = this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements != null
                                ? this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements.Count()
                                : 0;
                return "Resource Requirements (" + count + ")";
            }
        }

        public List<string> AvailableTags { get; internal set; }


        public string NewTagToBeAdded
        {
            get { return this.newTagToBeAdded; }
            set
            {
                this.newTagToBeAdded = value;
                this.OnPropertyChanged(PropertyNames.NewTagToBeAdded);
            }
        }

        public ICommand AddOsVhdTagCommand
        {
            get;
            private set;
        }

        public bool CanAddTag(string tag)
        {
            return !string.IsNullOrEmpty(tag) &&
                this.osvhdrequirements.FirstOrDefault(x => string.Equals(x.Tag, tag, StringComparison.Ordinal)) == null &&
                ParameterizationHelper.IsNotParameterized(this.NewTagToBeAdded);
        }

        public bool CanRemoveTag(string tag)
        {
            return this.osvhdrequirements.First(x => string.Equals(x.Tag, tag, StringComparison.Ordinal)) != null;
        }

        public void AddTag(string tag)
        {
            this.osvhdrequirements.Add(new OsVhdTagViewModel(tag, this));
            this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements = this.osvhdrequirements.Select(vhdTag => vhdTag.Tag).ToList();
            this.OnPropertyChanged(PropertyNames.OSVirtualHardDiskRequirements);
            this.OnPropertyChanged(PropertyNames.ResourceRequirementsSummary);
            this.NewTagToBeAdded = string.Empty;
            this.OnPropertyChanged(PropertyNames.NewTagToBeAdded);
        }

        public void RemoveTag(string tag)
        {
            var osVhdTag = this.osvhdrequirements.First(x => string.Equals(x.Tag, tag, StringComparison.OrdinalIgnoreCase));
            if (osVhdTag != null)
            {
                this.osvhdrequirements.Remove(osVhdTag);
                this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements = this.osvhdrequirements.Select(vhdTag => vhdTag.Tag).ToList();
                this.OnPropertyChanged(PropertyNames.OSVirtualHardDiskRequirements);
                this.OnPropertyChanged(PropertyNames.ResourceRequirementsSummary);
            }
        }

        public ObservableCollection<OsVhdTagViewModel> OSVirtualHardDiskRequirements
        {
            get { return this.osvhdrequirements; }
        }

        protected override void LoadChildren()
        {
            // No children                          
        }

        public string this[string propertyName]
        {
            get
            {
                string error = null;
                switch (propertyName)
                {
                    case PropertyNames.NewTagToBeAdded:
                        if (!string.IsNullOrEmpty(this.NewTagToBeAdded))
                        {                            
                            if (ParameterizationHelper.IsFullyParameterized(this.NewTagToBeAdded))                       
                            {
                                error = "Cannot parameterize tags";                                
                            }
                            if (error == null)
                            {
                                error = ValidationHelper.ValidateTags(this.NewTagToBeAdded, this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition.ResourceRequirements.OSVirtualHardDiskRequirements);                                                                                                                                                       
                            }                            
                        }
                        break;
                }
                return error;
            }
        }

        public string Error { get; set; }

        public ObservableCollection<CloudServiceModelValidationResult> ValidationResults { get; private set; }

        public void UpdateValidationResults()
        {
            this.IsExpanded = true;
            ModelValidationResultsHelper.UpdateValidationResults(this, typeof(PropertyNames));
            //Add any other cross-field validations error            
        }

        public string GetWarning(string propertyName)
        {
            string warning = null;
            switch (propertyName)
            {
                case PropertyNames.OSVirtualHardDiskRequirements:
                    if (this.osvhdrequirements == null || this.osvhdrequirements.Count == 0)
                    {
                        warning = "Specify OS Virtual Hard disk requirement tags";
                    }                    
                    break;
            }
            return warning;
        }
    }


}
